package com.trust.walletcore.example.utils


import android.util.Base64.encodeToString
import android.util.Log
import com.google.gson.Gson
import com.google.protobuf.ByteString
import com.trust.walletcore.example.utils.SolanaTransactionSender.toHexString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONArray
import org.json.JSONObject
import wallet.core.java.AnySigner
import wallet.core.jni.Base58

import wallet.core.jni.CoinType
import wallet.core.jni.PrivateKey
import wallet.core.jni.proto.Solana
import kotlin.experimental.and

import wallet.core.jni.PublicKey
import wallet.core.jni.SolanaAddress

object SolanaTransactionSender {
    private val client = OkHttpClient()
    private val gson = Gson()

    private const val TAG = "SolanaTransactionSender"


    // public val solanaRpcUrl="https://api.devnet.solana.com"

    // Solana 主网 RPC 节点
    // val url = "https://api.mainnet-beta.solana.com"

    public const val solanaRpcUrl =
        "https://solana-devnet.g.alchemy.com/v2/L14v0cudWOLilts5mklwB5WT3fUSl4oC"

    // 获取最近的区块哈希
    suspend fun getRecentBlockhash(): String {
//        val requestBody = """
//        {
//            "jsonrpc": "2.0",
//            "id": 1,
//            "method": "getRecentBlockhash",
//            "params": [{"commitment": "finalized"}]
//        }
//        """.trimIndent()

        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getLatestBlockhash"
        }
        """.trimIndent()

        Log.d("logcat", "获取最近的区块哈希.requestBody:$requestBody")

        val request = Request.Builder()
            //.url("https://api.devnet.solana.com")
            .url(solanaRpcUrl)
            .post(requestBody.toRequestBody("application/json".toMediaType()))
            .build()

        val response = client.newCall(request).execute()

        val jsonResponse = JSONObject(response.body!!.string())

        val latestBlockhash = jsonResponse.optJSONObject("result")
            ?.optJSONObject("value")
            ?.optString("blockhash") + ""
        Log.d("logcat", "获取最近的区块哈希:$latestBlockhash")
        return latestBlockhash
    }

    /**
     * 将签名后的交易发送到 Solana 网络
     */

    fun sendSignedTransaction(signedTransaction: ByteArray): String? {

        val transactionBase64 =
            android.util.Base64.encodeToString(signedTransaction, android.util.Base64.NO_WRAP)

        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendTransaction",
            "params": [
                "$transactionBase64"，
                 "${signedTransaction.toHexString()}"
            ]
        }
    """.trimIndent()

        val request = Request.Builder()
            .url(solanaRpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()

        client.newCall(request).execute().use { response ->
            return if (response.isSuccessful) {
                val jsonResponse = JSONObject(response.body!!.string())
                jsonResponse.getString("result")
            } else {
                Log.e(TAG,"Error sending transaction: ${response.message}")
                null
            }
        }
    }


    /**
     * 通过 RPC 获取交易签名记录
     */
    fun getTransactionSignatures(
        walletAddress: String,
        rpcUrl: String = solanaRpcUrl,
        limit: Int = 10
    ): List<String>? {
        val client = OkHttpClient()
        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getSignaturesForAddress",
            "params": [
                "$walletAddress",
                { "limit": $limit }
            ]
        }
    """.trimIndent()

        val request = Request.Builder()
            .url(rpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()

        client.newCall(request).execute().use { response ->
            if (response.isSuccessful) {
                val jsonResponse = JSONObject(response.body!!.string())
                val resultArray = jsonResponse.getJSONArray("result")

                // 提取签名列表
                return List(resultArray.length()) { index ->
                    resultArray.getJSONObject(index).getString("signature")
                }
            } else {
                println("Error fetching signatures: ${response.message}")
                return null
            }
        }
    }

    // 构建并签名转账交易 SOL 代币（原生 SOL）
    fun signTransferTransaction(
        receiverAddress: String,//接受者地址
        amount: Long, // 转账金额
        privateKeySolana: PrivateKey,//钱包私钥
        blockhash: String//最近的区块哈希
    ): String {
        val transferMessage = Solana.Transfer.newBuilder().apply {
            recipient = receiverAddress
            value = amount

        }.build()
        // TrustWalletCore 签名
        val signingInput = Solana.SigningInput.newBuilder().apply {
            this.privateKey = ByteString.copyFrom(privateKeySolana.data())
            this.recentBlockhash = blockhash
            this.transferTransaction = transferMessage
        }.build()

        val signingOutput =
            AnySigner.sign(signingInput, CoinType.SOLANA, Solana.SigningOutput.parser())

        val signedTransaction = signingOutput.encoded.toByteArray().toHexString(false)

        Log.d(TAG, "转账交易 Signed transaction: \n$signedTransaction")
        return signedTransaction
    }


    /**
     * SPL 代币（如 USDC, RAY）
     */
    fun signSPLTokenTransferTransaction(
        receiverTokenAccount: String, // 接收者的 SPL Token 账户（而不是主地址）
        mintAddress: String, // 代币合约地址
        amounts: Long, // 代币数量（注意是最小单位）
        privateKeySolana: PrivateKey, // 私钥
        blockhash: String // 区块哈希
    ): String {

        // 1. 计算发送方和接收方的关联代币账户（ATA）

        val tokenTransferMessage = Solana.TokenTransfer.newBuilder().apply {
            //  senderTokenAddress =
            recipientTokenAddress = receiverTokenAccount // 接收者 SPL Token 账户
            amount = amounts // 代币数量（最小单位）
            tokenMintAddress = mintAddress // 代币合约地址
        }.build()

        val signingInput = Solana.SigningInput.newBuilder().apply {
            this.privateKey = ByteString.copyFrom(privateKeySolana.data())
            this.recentBlockhash = blockhash
            this.tokenTransferTransaction = tokenTransferMessage // 使用 TokenTransfer
        }.build()

        val signingOutput =
            AnySigner.sign(signingInput, CoinType.SOLANA, Solana.SigningOutput.parser())

        val signedTransaction = signingOutput.encoded.toByteArray().toHexString(false)

        return signedTransaction
    }


    private fun ByteArray.toHexString(withPrefix: Boolean = true): String {
        val stringBuilder = StringBuilder()
        if (withPrefix) {
            stringBuilder.append("0x")
        }
        for (element in this) {
            stringBuilder.append(String.format("%02x", element and 0xFF.toByte()))
        }
        return stringBuilder.toString()
    }


    // 从 Solana DevNet 水龙头请求代币（1 SOL = 1_000_000_000 lamports）
    suspend fun requestTestSOL(address: String): String {
        return withContext(Dispatchers.IO) {
            try {
                // 1. 验证地址有效性
                if (!CoinType.SOLANA.validate(address)) {
                    return@withContext "地址无效：$address"
                }

                // 2. 构建 JSON-RPC 请求
                val jsonBody = """
                {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "requestAirdrop",
                    "params": ["$address", 1000000000] // 请求 1 SOL
                }
                """.trimIndent()

                val request = Request.Builder()
                    .url(solanaRpcUrl) // Solana DevNet 水龙头
                    .post(jsonBody.toRequestBody("application/json".toMediaType()))
                    .build()

                // 3. 发送请求
                val response = client.newCall(request).execute()
                val responseBody = response.body?.string() ?: return@withContext "请求失败：空响应"

                // 4. 解析结果
                val json = JSONObject(responseBody)
                if (json.has("error")) {
                    val error = json.getJSONObject("error")
                    "水龙头请求失败：${error.getString("message")}"
                } else {
                    val txId = json.getJSONObject("result").getString("value")
                    "成功领取 1 SOL！交易哈希：$txId"
                }
            } catch (e: Exception) {
                Log.e(TAG, "请求异常：${e.message}")
                "网络错误：${e.message}"
            }
        }
    }

    /**
     *
     * 领取测试代币
     * 调用水龙头 API 申请领取测试币，假设solanaRpcUrl就是请求地址
     * return true ：Tokens successfully requested for wallet: $walletAddress
     * return false ：Failed to request tokens: ${response.message}
     */

    fun requestTestTokens(walletAddress: String): Boolean {
        val client = OkHttpClient()
        val requestBody = """
        {
            "recipient": "$walletAddress"
        }
    """.trimIndent()

        val request = Request.Builder()
            .url(solanaRpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()

        client.newCall(request).execute().use { response ->
            return if (response.isSuccessful) {
                println("Tokens successfully requested for wallet: $walletAddress")
                true
            } else {
                println("Failed to request tokens: ${response.message}")
                false
            }
        }
    }


    /**
     *   通过 RPC 获取某个 SPL 代币的余额
     */

    fun getTokenBalance(
        rpcUrl: String = solanaRpcUrl, // Solana Devnet RPC
        walletAddress: String,                           // Wallet 地址
        tokenMintAddress: String                        // 代币 Mint Address
    ): String? {
        val client = OkHttpClient()
        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getTokenAccountsByOwner",
            "params": [
                "$walletAddress",
                {
                    "mint": "$tokenMintAddress"
                },
                {
                    "encoding": "jsonParsed"
                }
            ]
        }
    """.trimIndent()

        val request = Request.Builder()
            .url(rpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()

        client.newCall(request).execute().use { response ->
            if (response.isSuccessful) {
                val jsonResponse = JSONObject(response.body!!.string())
                val valueArray = jsonResponse.getJSONObject("result").getJSONArray("value")
                if (valueArray.length() > 0) {
                    val accountInfo = valueArray.getJSONObject(0)
                    val balance = accountInfo.getJSONObject("account")
                        .getJSONObject("data")
                        .getJSONObject("parsed")
                        .getJSONObject("info")
                        .getString("tokenAmount")
                    return balance
                } else {
                    println("No token accounts found for the specified mint.")
                    return null
                }
            } else {
                println("Error fetching token balance: ${response.message}")
                return null
            }
        }
    }


    // 发送交易到网络
    suspend fun sendTransaction(signedTx: String): String {
      // val base64Tx = android.util.Base64.encodeToString(signedTx, android.util.Base64.NO_WRAP)

        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendTransaction",
            "params": ["$signedTx"]
            
        }
        """.trimIndent()

        Log.d("logcat", "发送交易到网络.requestBody:$requestBody")

        val request = Request.Builder()
            .url(solanaRpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()



        client.newCall(request).execute().use { response ->
            return if (response.isSuccessful) {
                   response.body!!.string()
            } else {
                "Error sending transaction: ${response.message}"

            }
        }

//        val response = client.newCall(request).execute()
//        return response.body?.string() ?: "Error: Empty response"
//        if (response.isSuccessful) {
//            val jsonResponse = JSONObject(response.body!!.string())
//            return jsonResponse.toString()
//           // return jsonResponse.getJSONObject("result").getString("txid") // 返回交易哈希
//        } else {
//            return ("发送交易失败:" + response.body?.string()) ?: "Error: Empty response"// 返回
//          //  throw Exception("发送交易失败: ${response.message}")
//        }
    }

    fun sendTransaction2(signedTx: ByteArray) {

        val base58EncodedTx = Base58.encode(signedTx)
       // val url = "https://api.mainnet-beta.solana.com"
        val jsonRequest = JSONObject()
        jsonRequest.put("jsonrpc", "2.0")
        jsonRequest.put("id", 1)
        jsonRequest.put("method", "sendTransaction")
        val params = JSONArray()
        params.put(base58EncodedTx)
        jsonRequest.put("params", params)

        val jsonString = jsonRequest.toString()
        val mediaType = "application/json; charset=utf-8".toMediaTypeOrNull()
        val requestBody = jsonString.toRequestBody(mediaType)

        val request = Request.Builder()
            .url(solanaRpcUrl)
            .post(requestBody)
            .build()

        val client = OkHttpClient()
        client.newCall(request).execute().use { response ->
            if (!response.isSuccessful) {
                Log.e("logcat", "Transaction failed: ${response.code} - ${response.message}")
                response.body?.string()?.let { Log.e("logcat", "Response: $it") }
            } else {
                Log.d("logcat", "Transaction successful: ${response.body?.string()}")
            }
        }
    }


//    fun buyNft(
//        privateKeyHex: String, // 钱包的私钥（16进制字符串）
//        nftMintAddress: String, // NFT 的 Mint 地址
//        metadataAccount: String, // Metadata Account 地址
//        editionAccount: String, // Edition Account 地址
//        associatedTokenAccount: String, // NFT 的关联 Token Account 地址
//        recentBlockhash: String, // 最新的区块哈希
//        rpcUrl: String, // Solana Devnet 的 RPC URL
//    ): String? {
//        // 使用 Trust Wallet Core 初始化私钥
//        val privateKey = PrivateKey(privateKeyHex.toByteArray())
//        val payerAddress = CoinType.SOLANA.deriveAddress(privateKey) // 钱包地址
//
//        // 构建 Solana 签名输入
//        val signingInput = Solana.SigningInput.newBuilder().apply {
//            this.recentBlockhash = recentBlockhash // 设置区块哈希
//            this.feePayer = payerAddress // 支付者的地址
//
//            // 构建 `buyNft` 的调用指令
//            val instruction = Solana.Instruction.newBuilder().apply {
//                programId = "6zMNYYnqdVorfvmPHQNKz9D33iDeWahVHbdoKFTPc8xY" // 合约地址
//                // 设置 `buyNft` 的参数
//                accountsList.addAll(
//                    listOf(
//                        Solana.AccountMeta.newBuilder().setPubkey(payerAddress).setIsSigner(true).setIsWritable(true).build(),
//                        Solana.AccountMeta.newBuilder().setPubkey(metadataAccount).setIsSigner(false).setIsWritable(true).build(),
//                        Solana.AccountMeta.newBuilder().setPubkey(editionAccount).setIsSigner(false).setIsWritable(true).build(),
//                        Solana.AccountMeta.newBuilder().setPubkey(nftMintAddress).setIsSigner(true).setIsWritable(true).build(),
//                        Solana.AccountMeta.newBuilder().setPubkey(associatedTokenAccount).setIsSigner(false).setIsWritable(true).build(),
//                        Solana.AccountMeta.newBuilder().setPubkey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").setIsSigner(false).setIsWritable(false).build(), // SPL Token 程序
//                        Solana.AccountMeta.newBuilder().setPubkey("BPFLoaderUpgradeab1e11111111111111111111111").setIsSigner(false).setIsWritable(false).build(), // Associated Token 程序
//                        Solana.AccountMeta.newBuilder().setPubkey("11111111111111111111111111111111").setIsSigner(false).setIsWritable(false).build(), // System 程序
//                    )
//                )
//                // 设置方法参数，例如 tokenName, tokenSymbol, tokenUri (此处参数为示例)
//                data = ByteString.copyFromUtf8("tokenName:MyNFT,tokenSymbol:NFT,tokenUri:https://example.com")
//            }.build()
//
//            // 添加指令到消息中
//            addMessages(
//                Solana.Message.newBuilder().apply {
//                    instructionsList.add(instruction)
//                }.build()
//            )
//
//            // 设置私钥
//            addPrivateKey(ByteString.copyFrom(privateKey.data()))
//        }.build()
//
//        // 签名交易
//        val signingOutput = AnySigner.sign(signingInput, CoinType.SOLANA, Solana.SigningOutput.parser())
//        val signedTransaction = signingOutput.encoded.toByteArray()
//
//        // 发送交易到 RPC
//        return sendTransactionToRpc(signedTransaction, rpcUrl)
//    }

    // RPC 调用发送交易
    fun sendTransactionToRpc(signedTransaction: ByteArray, rpcUrl: String): String? {

        val transactionBase64 =
            android.util.Base64.encodeToString(signedTransaction, android.util.Base64.NO_WRAP)

        val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "sendTransaction",
            "params": ["$transactionBase64"]
        }
    """.trimIndent()

        val request = Request.Builder()
            .url(rpcUrl)
            .post(RequestBody.create("application/json".toMediaTypeOrNull(), requestBody))
            .build()

        client.newCall(request).execute().use { response ->
            return if (response.isSuccessful) {
                val jsonResponse = JSONObject(response.body!!.string())
                jsonResponse.getString("result")
            } else {
                println("Error sending transaction: ${response.message}")
                null
            }
        }
    }


    /**
     * Solana 查询某个地址的余额（SOL）
     */
    fun getSolBalance(address: String): Double {


        val client = OkHttpClient()

        // 构建 JSON-RPC 请求体
        val jsonBody = """
        {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getBalance",
            "params": [
                "$address"
            ]
        }
    """

        val request = Request.Builder()
            .url(solanaRpcUrl)
            .post(okhttp3.RequestBody.create("application/json".toMediaTypeOrNull(), jsonBody))
            .build()

        val response = client.newCall(request).execute()

        if (response.isSuccessful) {
            val jsonResponse = JSONObject(response.body!!.string())
            val balanceLamports = jsonResponse.getJSONObject("result").getLong("value")

            // 转换 Lamports 为 SOL（1 SOL = 1_000_000_000 Lamports）
            return balanceLamports / 1_000_000_000.0
        } else {
            throw Exception("查询余额失败: ${response.message}")
        }
    }


}

